//
// Created by 郝羽 on 2017/12/15.
//

#ifndef RTC_XSWITCH2_PACKET_HIST_TEST_HPP
#define RTC_XSWITCH2_PACKET_HIST_TEST_HPP

#include "test/catch.hpp"

#include <algorithm>
#include <cstdint>
#include <vector>

#include "bwe/packet_hist.hpp"

class PacketInfo : public bwe::PacketInfo {
public:
    PacketInfo() : bwe::PacketInfo(-1, 0, 0) {}
    PacketInfo(uint16_t seq, uint16_t bytes, uint32_t rtp_ts) : bwe::PacketInfo(seq, bytes, rtp_ts) {}
    bool operator== (const PacketInfo& other) const {
        return seq == other.seq && bytes == other.bytes && rtp_ts == other.rtp_ts;
    }
};

TEST_CASE("add one packet", "[packet history]") {
    const uint16_t seq = 10;
    PacketInfo send(seq, 1, 1);
    PacketInfo recv, recv2;

    bwe::PacketHistory<128> hist;
    hist.insert_packet(send);

    REQUIRE(hist.get(recv, seq));
    REQUIRE(recv == send);
    REQUIRE(hist.get(recv2, seq));
    REQUIRE(recv2 == send);
}

TEST_CASE("add some packets", "[packet history]") {
    std::vector<PacketInfo> send;
    std::vector<PacketInfo> recv;
    bwe::PacketHistory<128> hist;
    const int n = 128;
    const uint16_t seq = 100;
    const uint16_t size = 100;
    const uint32_t rtp_ts = 100;
    for (auto i = 0; i < n; ++i) {
        send.push_back(PacketInfo(seq+i, size+i, rtp_ts+i));
        recv.push_back(PacketInfo(seq+i, 0, 0));
    }
    for (auto i = 0; i < n; ++i) {
        hist.insert_packet(send[i]);
    }
    std::random_shuffle(recv.begin(), recv.end());
    for (auto i = 0; i < n; ++i) {
        PacketInfo r = recv[i];
        REQUIRE(hist.get(r, r.seq));
        REQUIRE(r == send[r.seq-seq]);
    }
}

TEST_CASE("remove old packets", "[packet history]") {
    bwe::PacketHistory<128> hist;

    const uint16_t seq = 100;
    const uint16_t size = 100;
    const uint32_t rtp_ts = 100;
    for (auto i = 0; i < 256; ++i) {
        hist.insert_packet(PacketInfo(seq+i, size+i, rtp_ts+i));
    }
    for (auto i = 0; i < 128; ++i) {
        PacketInfo p;
        REQUIRE(!hist.get(p, i+seq));
    }
    for (auto i = 128; i < 256; ++i) {
        PacketInfo p;
        hist.get(p, i);

        REQUIRE(hist.get(p, i+seq));
    }
}

TEST_CASE("wrapping", "[packet history]") {
    bwe::PacketHistory<128> hist;
    hist.insert_packet(PacketInfo(65535, 65535, 65535));
    hist.insert_packet(PacketInfo(0, 0, 0));
    PacketInfo p;
    REQUIRE(hist.get(p, 65535));
    hist.insert_packet(PacketInfo(127, 127, 127));
    REQUIRE(!hist.get(p, 65535));
}
#endif //RTC_XSWITCH2_PACKET_HIST_TEST_HPP